package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {

    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;

    @Autowired
    private GraphInfoMapper graphInfoMapper;

    @Autowired
    private LabelInfoMapper labelInfoMapper;

    @Autowired
    private FacilityInfoMapper facilityInfoMapper;

    @Autowired
    private FeeValueMapper feeValueMapper;

    @Autowired
    private GraphInfoService graphInfoService;

    @Autowired
    private ApartmentLabelService apartmentLabelService;

    @Autowired
    private ApartmentFacilityService apartmentFacilityService;

    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;

    @Autowired
    private RoomInfoMapper roomInfoMapper;


    /**
     * 根据条件分页查询公寓列表
     *
     * @param page    分页对象
     * @param queryVo 查询条件
     * @return 当前页数据列表
     */
    @Override
    public IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        return apartmentInfoMapper.pageApartmentItemByQuery(page, queryVo);
    }

    /**
     * 根据ID获取公寓详细信息
     *
     * @param id 公寓ID
     * @return 公寓信息
     */
    @Override
    public ApartmentDetailVo getApartmentDetailById(Long id) {

        // 业务层组装 ApartmentDetailVo ：减轻多表联查压力
        // ApartmentDetailVo = ApartmentInfo + graphVoList + labelInfoList + facilityInfoList + feeValueVoList

        // 1. 公寓基本信息 ApartmentInfo
        ApartmentInfo apartmentInfo = this.getById(id);

        // 2. 公寓图片信息列表 graphVoList
        List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT, id);

        // 3. 公寓标签信息列表 labelInfoList
        List<LabelInfo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);

        // 4. 公寓配套信息列表 facilityInfoList
        List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectListByApartmentId(id);

        // 5. 公寓杂费信息列表 feeValueVoList
        List<FeeValueVo> feeValueVoList = feeValueMapper.selectListByApartmentId(id);

        // 6. 组装 ApartmentDetailVo 数据
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        // 组装 ApartmentInfo
        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
        // 组装 graphVoList
        apartmentDetailVo.setGraphVoList(graphVoList);
        // 组装 labelInfoList
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        // 组装 facilityInfoList
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        // 组装 feeValueVoList
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);

        return apartmentDetailVo;
    }

    /**
     * 保存或更新公寓信息
     *
     * @param apartmentSubmitVo 公寓信息
     */
    @Override
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {

        // apartmentSubmitVo = ApartmentInfo（公寓基本信息） + facilityInfoIds（配套信息的id列表） + labelIds（公寓标签的id列表） + feeValueIds（公寓杂费id列表） + graphVoList（图片信息Vo）

        // 判断传递过来的公寓信息是否包含id值，包含则说明其是在数据库中已经存在的公寓，需要进行更新操作，不包含则说明数据库中不存在该公寓，需要进行保存操作
        boolean isUpdate = apartmentSubmitVo.getId() != null;

        // 无论是保存还是更新，公寓的基础信息都使用MyBatisPlus提供的持久层接口IService中的方法自动进行
        // 无论是更新还是保存，执行完之后就有id了
        this.saveOrUpdate(apartmentSubmitVo);

        // 如果是更新操作，则直接删除其他表中关于公寓的关联信息（不考虑对比删除修改信息），冗余信息
        if (isUpdate) {
            // 1. 删除图片信息
            LambdaQueryWrapper<GraphInfo> graphLambdaQueryWrapper = new LambdaQueryWrapper<>();
            graphLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
            graphLambdaQueryWrapper.eq(GraphInfo::getItemId, apartmentSubmitVo.getId());
            graphInfoService.remove(graphLambdaQueryWrapper);


            // 2. 删除配套信息
            LambdaQueryWrapper<ApartmentFacility> facilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
            facilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId, apartmentSubmitVo.getId());
            apartmentFacilityService.remove(facilityLambdaQueryWrapper);

            // 3. 删除标签信息
            LambdaQueryWrapper<ApartmentLabel> labelLambdaQueryWrapper = new LambdaQueryWrapper<>();
            labelLambdaQueryWrapper.eq(ApartmentLabel::getApartmentId, apartmentSubmitVo.getId());
            apartmentLabelService.remove(labelLambdaQueryWrapper);

            // 4. 删除杂费信息
            LambdaQueryWrapper<ApartmentFeeValue> feeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            feeLambdaQueryWrapper.eq(ApartmentFeeValue::getApartmentId, apartmentSubmitVo.getId());
            apartmentFeeValueService.remove(feeLambdaQueryWrapper);
        }

        // 1. 保存图片信息
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        // 非空判断
        if (!CollectionUtils.isEmpty(graphVoList)) {
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            // GraphVo转换GraphInfo
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfo.setItemId(apartmentSubmitVo.getId());
                graphInfo.setName(graphVo.getName());
                graphInfo.setUrl(graphVo.getUrl());
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }

        // 2. 保存配套信息列表
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIds)) {
            ArrayList<ApartmentFacility> facilityList = new ArrayList<>();
            for (Long facilityInfoId : facilityInfoIds) {
                ApartmentFacility apartmentFacility = new ApartmentFacility();
                apartmentFacility.setApartmentId(apartmentSubmitVo.getId());
                apartmentFacility.setFacilityId(facilityInfoId);
                facilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(facilityList);
        }

        // 3. 保存标签信息列表
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        if (!CollectionUtils.isEmpty(labelIds)) {
            ArrayList<ApartmentLabel> labelList = new ArrayList<>();
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = new ApartmentLabel();
                apartmentLabel.setApartmentId(apartmentSubmitVo.getId());
                apartmentLabel.setLabelId(labelId);
                labelList.add(apartmentLabel);
            }
            apartmentLabelService.saveBatch(labelList);
        }

        // 4. 保存杂费信息列表
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        if (!CollectionUtils.isEmpty(feeValueIds)) {
            ArrayList<ApartmentFeeValue> feeValueList = new ArrayList<>();
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                apartmentFeeValue.setApartmentId(apartmentSubmitVo.getId());
                apartmentFeeValue.setFeeValueId(feeValueId);
                feeValueList.add(apartmentFeeValue);
            }
            apartmentFeeValueService.saveBatch(feeValueList);
        }
    }

    /**
     * 根据id删除公寓信息
     *
     * @param id 要删除的公寓id
     */
    @Override
    public void removApartmenteById(Long id) {

        // 判断公寓下是否还有房间
        LambdaQueryWrapper<RoomInfo> roomQueryWrapper = new LambdaQueryWrapper<>();
        roomQueryWrapper.eq(RoomInfo::getApartmentId, id);
        Long count = roomInfoMapper.selectCount(roomQueryWrapper);
        // 公寓下还有房间
        if (count > 0) {
            // 抛出异常，提醒先删除子集
            throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
        }

        // 公寓下没有空房间则开始删除

        // 1. 删除GraphInfo图片信息
        LambdaQueryWrapper<GraphInfo> graphLambdaQueryWrapper = new LambdaQueryWrapper<>();
        graphLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
        graphLambdaQueryWrapper.eq(GraphInfo::getItemId, id);
        graphInfoService.remove(graphLambdaQueryWrapper);


        // 2. 删除ApartmentFacility配套信息
        LambdaQueryWrapper<ApartmentFacility> facilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        facilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId, id);
        apartmentFacilityService.remove(facilityLambdaQueryWrapper);

        // 3. 删除ApartmentLabel标签信息
        LambdaQueryWrapper<ApartmentLabel> labelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        labelLambdaQueryWrapper.eq(ApartmentLabel::getApartmentId, id);
        apartmentLabelService.remove(labelLambdaQueryWrapper);

        // 4. 删除ApartmentFeeValue杂费信息
        LambdaQueryWrapper<ApartmentFeeValue> feeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        feeLambdaQueryWrapper.eq(ApartmentFeeValue::getApartmentId, id);
        apartmentFeeValueService.remove(feeLambdaQueryWrapper);

        // 5. 删除ApartmentInfo公寓
        this.removeById(id);
    }
}




